
#define MinY 100.0

float box(vec2 p, vec2 size, float radius) {
	size -= vec2(radius);
	vec2 d = abs(p) - size;
  	return min(max(d.x, d.y), 0.0) + length(max(d, 0.0)) - radius;
}

float boxDist(vec2 p, vec2 boxOrg, vec2 boxSize, float radius){
    return box(p-boxOrg, boxSize, radius);
}

//获取p点的SDF(Signed-Distance-Field)值
float sdf(vec2 p) {
    float a1 =  boxDist(p, vec2(200.0, 150.0+MinY), vec2(40.0, 40.0), 0.0);
    float a2 =  boxDist(p, vec2(350.0, 250.0+MinY), vec2(40.0, 40.0), 0.0);
    float a3 =  boxDist(p, vec2(500.0, 150.0+MinY), vec2(40.0, 40.0), 0.0);
    float a4 =  boxDist(p, vec2(500.0, 350.0+MinY), vec2(40.0, 40.0), 0.0);
    float a5 =  boxDist(p, vec2(100.0, 350.0+MinY), vec2(40.0, 40.0), 0.0);
    float l = min(min(min(min(a1, a2), a3), a4), a5);
    return l/max(iResolution.x, iResolution.y);
}

float sdf_uv(vec2 p) {
    float a1 =  boxDist(p, vec2(200.0, 150.0+MinY)/iResolution.xy, vec2(40.0, 40.0)/iResolution.xy, 0.0);
    float a2 =  boxDist(p, vec2(350.0, 250.0+MinY)/iResolution.xy, vec2(40.0, 40.0)/iResolution.xy, 0.0);
    float a3 =  boxDist(p, vec2(500.0, 150.0+MinY)/iResolution.xy, vec2(40.0, 40.0)/iResolution.xy, 0.0);
    float a4 =  boxDist(p, vec2(500.0, 350.0+MinY)/iResolution.xy, vec2(40.0, 40.0)/iResolution.xy, 0.0);
    float a5 =  boxDist(p, vec2(100.0, 350.0+MinY)/iResolution.xy, vec2(40.0, 40.0)/iResolution.xy, 0.0);
    float l = min(min(min(min(a1, a2), a3), a4), a5);
    return l/max(iResolution.x, iResolution.y);
}

#define EPSILON 0.01
#define MAX_MARCHING_STEPS 64
#define Sebastian 1
float shadow(vec2 light, vec2 pos, float hard) {
	float l = abs(length( light - pos));
    vec2  viewRayDirection = (light-pos)/l;

    float res = 1./hard;
    float dt = 0.01;

    float ph = 1e20;

    //最多尝试MAX_MARCHING_STEPS次
    for (int i = 0; i < MAX_MARCHING_STEPS; ++i){
        float sd = sdf(pos + viewRayDirection*dt)*max(iResolution.x, iResolution.y);
        if (sd < EPSILON) {return 0.0;}

#if Sebastian       
        //GDC 2018,Sebastian Aaltonen
        float y = sd*sd/(2.0*ph);
        float d = sqrt(sd*sd-y*y);
        res = min( res, d/max(0.0,dt-y));
        ph = sd;
#else
        res = min(res, sd/dt);
#endif
        if (res<=0.001) {res = 0.0; break;}
        
        dt += max(1.0, abs(sd));
		if (dt >= l) break;
    }
    
    return smoothstep(0.0,1.0, res*hard);
}

float shadow_uv(vec2 light, vec2 pos, float hard) {
    vec2  d = light - pos;
	float l = length(d);
    float res = 1.;
    
    for( float t=0.01, h=0.0; t < l; t+= h)
    {
        h = sdf_uv(pos + d/l*t);
        if( h < EPSILON ) return 0.;
        res = min(res, hard*h/t );
    }
    return res;
}


void mainImage( out vec4 fragColor, in vec2 fragCoord ) {
    //vec2 c = iResolution.xy / 2.0;	//画布中点
	vec2 mouseP = vec2(iMouse.x+0.0, iMouse.y+0.0);	//目标点
	//vec2 p = vec2(gl_FragCoord.x+0.0,gl_FragCoord.y+0.0);	//目标点
	vec2 uv = gl_FragCoord.xy/iResolution.xy;
    vec2 c_uv = vec2(0.5,0.5);
    vec2 mouse_uv = mouseP/iResolution.xy;

    vec4 col = vec4(1.0);
    
    col *= vec4(0.5, 0.5, 0.5, 1.0) * (1.0 - length(c_uv - uv));
        
    vec2 p = uv*iResolution.xy;
    col *= clamp(min(mod(p.x, 10.0), mod(p.y, 10.0)), 0.9, 1.0);


    col = sdf(p)<0.0?vec4(1.0, 0.5, 0.7, 1.0):col;
    //col = sdf_uv(uv)*vec4(0.8, 0.5, 0.7, 1.0);
    //col = sdf_uv(uv)>0.0?col:vec4(0.0, 0.0, 0.0, 1.0);

    col *= shadow(mouseP, p, 48.0);
    //col *= shadow_uv(mouse_uv, uv, 10.0);

    if (length(p-mouseP)<(4.0)) {
        col = vec4(1,1,1,1);
    }

    fragColor = clamp(col, 0.0, 1.0);
}